package pl.edu.pk.mech.kkbus.repository;

import static pl.edu.pk.mech.kkbus.staticstrings.NameEntity.NAME_ENTITY_AWARD;
import static pl.edu.pk.mech.kkbus.staticstrings.NameEntity.NAME_ENTITY_BUSSES;
import static pl.edu.pk.mech.kkbus.staticstrings.NameEntity.NAME_ENTITY_USERS;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_AUTHORITIES;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_BIRTH_DAY;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_EMAIL;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_ENABLED;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_HASH;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_NAME;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_PASS;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_PHONE;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_SURNAME;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_POINTS;
import static pl.edu.pk.mech.kkbus.staticstrings.UserProperty.USER_ROLES_DIVIDER;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import pl.edu.pk.mech.kkbus.datastore.common.SynchronizeCommon;
import pl.edu.pk.mech.kkbus.model.Award;
import pl.edu.pk.mech.kkbus.model.Bus;
import pl.edu.pk.mech.kkbus.model.Pojo;
import pl.edu.pk.mech.kkbus.model.User;
import pl.edu.pk.mech.kkbus.model.User.Role;
import pl.edu.pk.mech.kkbus.service.UserService;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

@Repository
public class UserDAO extends BaseDAO{
    
    private static final Logger log = Logger.getLogger(UserDAO.class.getName());
    
    @Autowired
    UserService userService;
    
	public boolean createOrUpdateUser(User user) {
		  Entity product = getEntity(user.getId(), NAME_ENTITY_USERS);
		    if (product == null) {
		    	if (!userService.ifEmailExisting(user.getEmail())) {
				      log.info("--- create new property "+NAME_ENTITY_USERS);
				      product = new Entity(NAME_ENTITY_USERS);
				      fillProperty(user, product);
				}else{
					log.info("--- user already existing");
					return false;
				}
		    } else {
		      log.info("--- update property "+NAME_ENTITY_USERS+" the key: "+product.getKey());
		      fillProperty(user, product);
		    }
	    return SynchronizeCommon.putEntityCacheAndStore(product);
	}
	
	public boolean updateUser(User user) {
		  Entity product = getEntity(user.getId(), NAME_ENTITY_USERS);
		    if (product != null) {
				 log.info("--- update user "+user.getEmail());
				 fillProperty(user, product);
				 product.setProperty(USER_ENABLED, true);
				 return SynchronizeCommon.putEntityCacheAndStore(product);
		    } else {
		      log.info("--- can not update user");
		      return false;
		    }
	}
	
	  public List<User> getUsers() {
		  List<User> temp = new ArrayList<User>();
		  Iterable<Entity> entityList = SynchronizeCommon.listEntities(NAME_ENTITY_USERS, null, null);
		  for (Entity entity : entityList) {
			  temp.add(new User(entity));
		  }
		  return temp;
	  }
	
	public boolean banUser(long id, boolean ban){
		Entity product = getEntity(id, NAME_ENTITY_USERS);
		if (product != null) {
			product.setProperty(USER_ENABLED, ban);
			return SynchronizeCommon.putEntityCacheAndStore(product);
		}
		return false;
	}
        
       
	
	public boolean deleteUser(long id){
		Key key = KeyFactory.createKey(NAME_ENTITY_USERS, id);
		return SynchronizeCommon.deleteEntity(key);
	}
	
	  public User getUser(long id){
	  	  Entity entityTemp = getEntity(id, NAME_ENTITY_USERS);
	  	  if (entityTemp != null) {
	  		  return new User(entityTemp);
	  	  }
		  return null;
	}
	
	public List<User> loadUserDUPA(ArrayList<Long> listId){
		  List<User> temp = new ArrayList<User>();
		  Iterable<Entity> entityList = SynchronizeCommon.getByID(NAME_ENTITY_USERS, "id", listId);
		  for (Entity entity : entityList) {
			  temp.add(new User(entity));
		  }
		  return temp;
	}
	
	public List<User> loadUserByRole(String role){
		  List<User> temp = new ArrayList<User>();
		  Iterable<Entity> entityList = SynchronizeCommon.listEntities(NAME_ENTITY_USERS, USER_AUTHORITIES, role);
		  for (Entity entity : entityList) {
			  temp.add(new User(entity));
		  }
		  return temp;
	}
	
	public boolean ifEmailExisting(String email){
		  Iterable<Entity> entityList = SynchronizeCommon.listEntities(NAME_ENTITY_USERS, USER_EMAIL, email);
		  if (entityList.iterator().hasNext()) {
			  return true;
		  }
		  return false;
	}
	
	public User loadUserByEmail(String email){
		  User temp = null;
		  Iterable<Entity> entityList = SynchronizeCommon.listEntities(NAME_ENTITY_USERS, USER_EMAIL, email);
		  for (Entity entity : entityList) {
			  temp = new User(entity);
		  }
		  return temp;
	}
        
        public User getUserByHash(String hash) {
            User user = null;
            
            Iterable<Entity> entityList = SynchronizeCommon.listEntities(NAME_ENTITY_USERS, USER_HASH, hash);
            for (Entity entity : entityList) {
                user = new User(entity);
            }
            
            return user;
        }
        
        public boolean setEnableUser(User user){
        	Entity product = getEntity(user.getId(), NAME_ENTITY_USERS);
        	product.setProperty(USER_ENABLED, true);
        	product.setProperty(USER_HASH, "");
        	return SynchronizeCommon.putEntityCacheAndStore(product);
        }

	@Override
	public void fillProperty(Pojo pojo, Entity entity) {
            User user = (User)pojo;
			
            Set<Role> authorities = user.getAuthorities();
            String roles = "";
            if (authorities != null) {
                for (Iterator iterator = authorities.iterator(); iterator.hasNext();) {
                    Role role = (Role)iterator.next();
                    roles += role.name() + USER_ROLES_DIVIDER;
    		}
                roles = roles.substring(0, roles.length() - 1);
            } else {
                roles = "USER";
            }
            
            entity.setProperty(USER_EMAIL, user.getEmail());
            entity.setProperty(USER_NAME, user.getName());
            entity.setProperty(USER_BIRTH_DAY, user.getBirthday());
            entity.setProperty(USER_PASS, user.getPassword());
            try {
                entity.setProperty(USER_SURNAME, new String(user.getSurname().getBytes("utf-8"),"utf-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            entity.setProperty(USER_ENABLED, user.isEnabled());
            entity.setProperty(USER_PHONE, user.getPhone());            
            entity.setProperty(USER_AUTHORITIES, roles);
            entity.setProperty(USER_HASH, user.getHash());
            entity.setProperty(USER_POINTS, user.getPoints());
            
        }
}
